/*****
 *
 *   The contents of this file were written by Kevin Lindsey
 *   copyright 2002-2003 Kevin Lindsey
 *
 *   This file was compacted by jscompact
 *   A Perl utility written by Kevin Lindsey (kevin@kevlindev.com)
 *
 *****/

Svg.VERSION = 1.0;
Svg.NAMESPACE = "http://www.w3.org/2000/svg";

function Svg() {
}

PathParser.PARAMCOUNT = {A: 7, C: 6, H: 1, L: 2, M: 2, Q: 4, S: 4, T: 2, V: 1, Z: 0};
PathParser.METHODNAME = {
    A: "arcAbs",
    a: "arcRel",
    C: "curvetoCubicAbs",
    c: "curvetoCubicRel",
    H: "linetoHorizontalAbs",
    h: "linetoHorizontalRel",
    L: "linetoAbs",
    l: "linetoRel",
    M: "movetoAbs",
    m: "movetoRel",
    Q: "curvetoQuadraticAbs",
    q: "curvetoQuadraticRel",
    S: "curvetoCubicSmoothAbs",
    s: "curvetoCubicSmoothRel",
    T: "curvetoQuadraticSmoothAbs",
    t: "curvetoQuadraticSmoothRel",
    V: "linetoVerticalAbs",
    v: "linetoVerticalRel",
    Z: "closePath",
    z: "closePath"
}

function PathParser() {
    this._lexer = new PathLexer();
    this._handler = null;
}

PathParser.prototype.parsePath = function (path) {
    if (path == null || path.namespaceURI != Svg.NAMESPACE || path.localName != "path") throw new Error("PathParser.parsePath: The first parameter must be an SVG path element");
    this.parseData(path.getAttributeNS(null, "d"));
};
PathParser.prototype.parseData = function (pathData) {
    if (typeof (pathData) != "string") throw new Error("PathParser.parseData: The first parameter must be a string");
    if (this._handler != null && this._handler.beginParse != null) this._handler.beginParse();
    var lexer = this._lexer;
    lexer.setPathData(pathData);
    var mode = "BOP";
    var token = lexer.getNextToken();
    while (!token.typeis(PathToken.EOD)) {
        var param_count;
        var params = new Array();
        switch (token.type) {
            case PathToken.COMMAND:
                if (mode == "BOP" && token.text != "M" && token.text != "m") throw new Error("PathParser.parseData: a path must begin with a moveto command");
                mode = token.text;
                param_count = PathParser.PARAMCOUNT[token.text.toUpperCase()];
                token = lexer.getNextToken();
                break;
            case PathToken.NUMBER:
                break;
            default:
                throw new Error("PathParser.parseData: unrecognized token type: " + token.type);
        }
        for (var i = 0; i < param_count; i++) {
            switch (token.type) {
                case PathToken.COMMAND:
                    throw new Error("PathParser.parseData: parameter must be a number: " + token.text);
                case PathToken.NUMBER:
                    params[i] = token.text - 0;
                    break;
                default:
                    throw new Errot("PathParser.parseData: unrecognized token type: " + token.type);
            }
            token = lexer.getNextToken();
        }
        if (this._handler != null) {
            var handler = this._handler;
            var method = PathParser.METHODNAME[mode];
            if (handler[method] != null) handler[method].apply(handler, params);
        }
        if (mode == "M") mode = "L";
        if (mode == "m") mode = "l";
    }
};
PathParser.prototype.setHandler = function (handler) {
    this._handler = handler;
};
PathLexer.VERSION = 1.0;

function PathLexer(pathData) {
    if (pathData == null) pathData = "";
    this.setPathData(pathData);
}

PathLexer.prototype.setPathData = function (pathData) {
    if (typeof (pathData) != "string") throw new Error("PathLexer.setPathData: The first parameter must be a string");
    this._pathData = pathData;
};
PathLexer.prototype.getNextToken = function () {
    var result = null;
    var d = this._pathData;
    while (result == null) {
        if (d == null || d == "") {
            result = new PathToken(PathToken.EOD, "");
        } else if (d.match(/^([ \t\r\n,]+)/)) {
            d = d.substr(RegExp.$1.length);
        } else if (d.match(/^([AaCcHhLlMmQqSsTtVvZz])/)) {
            result = new PathToken(PathToken.COMMAND, RegExp.$1);
            d = d.substr(RegExp.$1.length);
        } else if (d.match(/^(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)/)) {
            result = new PathToken(PathToken.NUMBER, parseFloat(RegExp.$1));
            d = d.substr(RegExp.$1.length);
        } else {
            throw new Error("PathLexer.getNextToken: unrecognized path data " + d);
        }
    }
    this._pathData = d;
    return result;
};
PathToken.UNDEFINED = 0;
PathToken.COMMAND = 1;
PathToken.NUMBER = 2;
PathToken.EOD = 3;

function PathToken(type, text) {
    if (arguments.length > 0) {
        this.init(type, text);
    }
}

PathToken.prototype.init = function (type, text) {
    this.type = type;
    this.text = text;
};
PathToken.prototype.typeis = function (type) {
    return this.type == type;
}